package com.workingpub.commons.jdbc.mapping;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.Entity;

/**
 * 非JPA注解映射
 * 
 * @author taoping
 *
 * @param <T>
 */
public class IntrospectorRowMapping<T> extends AbstractRowMapping<T> {
	private Map<String, PropertyDescriptor> beanProperties;

	@Override
	protected T mapping(Class<T> resultType, ResultSet rs, int rowNum) throws Exception {
		if (resultType.isAnnotationPresent(Entity.class)) {
			return null;
		}
		if (Map.class.isAssignableFrom(resultType)) {
			return null;
		}
		if (resultType.getName().startsWith("java.lang")) {
			return resultType.cast(convert(resultType, rs, (String) getColumnInfos().keySet().toArray()[0]));
		}
		if (null == beanProperties) {
			BeanInfo beanInfo = Introspector.getBeanInfo(resultType, Object.class);
			PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();
			beanProperties = new HashMap<String, PropertyDescriptor>();
			for (PropertyDescriptor entry : properties) {
				beanProperties.put(entry.getName(), entry);
			}
		}

		T result = null;
		for (Entry<String, PropertyDescriptor> entry : beanProperties.entrySet()) {
			if (!containColumn(entry.getValue().getName().toUpperCase())) {
				continue;
			}
			if (null == result) {
				result = resultType.newInstance();
			}

			Method writeMethod = entry.getValue().getWriteMethod();
			writeMethod.invoke(result, convert(writeMethod.getParameterTypes()[0], rs, entry.getValue().getName()));
		}

		return result;
	}
}
